#include "n_list.h"

struct nlist neighl;

int create_nlist(void){
	INIT_LIST_HEAD(&neighl.nlhead);
	neighl.nent = NULL;
	
	printk(KERN_INFO "DBG: Nlist created\n");
	return 0;
}

int destroy_nlist(void){
	struct list_head *pos, *q;
	struct nlist *tmpnl;
	
	list_for_each_safe(pos, q, &neighl.nlhead){
		tmpnl = list_entry(pos, struct nlist, nlhead);
//		printk(KERN_INFO "DBG: removed from nlist ent ID = %d\n", (tmpnl->nent->neigh_id_o));
		list_del(pos);
		vfree(tmpnl);
	}
	printk(KERN_INFO "DBG: Nlist destroyed\n");
	return 0;
}

int insert_nent(struct n_ent *ne){
	struct nlist *tmpnl;
	
	tmpnl = (struct nlist *)vmalloc(sizeof(struct nlist));
	
	printk(KERN_INFO"DBG: start insert_nent ne->ID = %u\n", (ne->neigh_id_o));
	if((find_nent(ne->neigh_id_o, (tmpnl->nent))) == 0){
		(tmpnl->nent) = ne;
		vfree(tmpnl);
		printk(KERN_INFO "DBG: ID found in nlist, updated\n");
	}else{
//		tmpnl = NULL;
		(tmpnl->nent) = ne;
//		printk(KERN_INFO"DBG: tmpnl->nent->ID = %u\n", (tmpnl->nent->neigh_id_o));
		list_add_tail(&(tmpnl->nlhead), &(neighl.nlhead));
		printk(KERN_INFO "DBG: Inserting new ent into nlist\n");
	}
	printk(KERN_INFO "DBG: nlist new ent ID = %u\n", (tmpnl->nent->neigh_id_o));

	return 0;
}

int find_nent(unsigned int nid, struct n_ent *retnent){
	struct list_head *pos;
	struct nlist *tmpnl;
	
	printk(KERN_INFO "DBG: start find_nent ID = %u\n", nid);
	list_for_each(pos, &neighl.nlhead){
		tmpnl = list_entry(pos, struct nlist, nlhead);
		if((tmpnl->nent->neigh_id_o) == nid){
			retnent = (tmpnl->nent);
			printk(KERN_INFO "DBG: ID found in nlist\n");
			return 0;
		}
	}
	printk(KERN_INFO "DBG: ID not found in nlist\n");
	return -1;
}

unsigned int find_best_nent(void){
	struct list_head *pos;
	struct nlist *tmpnl = NULL;
	u32 bestID = 0;
	u32 largest = 0;
	
	list_for_each(pos, &neighl.nlhead){
		tmpnl = list_entry(pos, struct nlist, nlhead);
		if((tmpnl->nent) != NULL){
			if((tmpnl->nent->free_space_o) > largest){
				bestID = tmpnl->nent->neigh_id_o;
			}
		}
	}
	
	if(bestID != 0){
			printk(KERN_INFO "DBG: Best candidate found in nlist\n");
			return bestID;
	}
	else{
		printk(KERN_INFO "DBG: Best candidate found in nlist\n");
		return 0;
	}
}

int remove_nent(struct n_ent *ne){
	struct list_head *pos, *q;
	struct nlist *tmpnl;
	
	list_for_each_safe(pos, q, &neighl.nlhead){
		tmpnl = list_entry(pos, struct nlist, nlhead);
		if((tmpnl->nent->neigh_id_o) == (ne->neigh_id_o)){
			list_del(pos);
			vfree(tmpnl);
			printk(KERN_INFO "DBG: ID found in nlist, removed\n");
			return 0;
		}
	}
	printk(KERN_INFO "DBG: ID not found in nlist, nothing to remove\n");
	return -1;
}


